local assets =
{
    Asset("ANIM", "anim/tf_floral_butterfly_fan.zip"),
    Asset("ANIM", "anim/tf_floral_butterfly_fan_proj.zip"),
}

local prefabs =
{
    "tf_floral_butterfly_fan_proj",
    "voidcloth_boomerang_launch_fx",
    "voidcloth_boomerang_impact_fx",
    "spoiled_food",
}

----------------------------------------------------------------------------------------------------------------

local function OnEquip(inst, owner)
    owner.AnimState:OverrideSymbol("swap_object", "tf_floral_butterfly_fan", "swap_tf_floral_butterfly_fan")
    owner.AnimState:Show("ARM_carry")
    owner.AnimState:Hide("ARM_normal")
end

local function OnUnequip(inst, owner)
    owner.AnimState:Hide("ARM_carry")
    owner.AnimState:Show("ARM_normal")
    local skin_build = inst:GetSkinBuild()
    if skin_build ~= nil then
        owner:PushEvent("unequipskinneditem", inst:GetSkinName())
    end
end

----------------------------------------------------------------------------------------------------------------

-- 没有能量了,武器不再是远程武器,无法发射射弹
local function OnDischarged(inst)
    inst.components.weapon:SetRange(nil)
    inst.components.weapon:SetProjectile(nil)
end

-- 有能量,设定武器的攻击距离,射弹是啥
local function OnCharged(inst)
    inst.components.weapon:SetRange(TUNING.VOIDCLOTH_BOOMERANG_ATTACK_DIST, TUNING.VOIDCLOTH_BOOMERANG_ATTACK_DIST_MAX)
    inst.components.weapon:SetProjectile("tf_floral_butterfly_fan_proj")
end

----------------------------------------------------------------------------------------------------------------

local function OnProjectileCountChanged(inst)
    if #inst._projectiles >= inst.max_projectiles then
        inst.components.rechargeable:Discharge(math.huge)
    else
        inst.components.rechargeable:SetPercent(1)
    end
end

----------------------------------------------------------------------------------------------------------------

local function OnPreLoad(inst, data, newents)
    if data ~= nil then
        -- 清除 rechargeable 数据,我们没有正常使用 rechargeable...
        data.rechargeable = nil
    end
end

----------------------------------------------------------------------------------------------------------------

local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()

    MakeInventoryPhysics(inst)
    RemovePhysicsColliders(inst)

    inst.AnimState:SetBank("tf_floral_butterfly_fan")
    inst.AnimState:SetBuild("tf_floral_butterfly_fan")
    inst.AnimState:PlayAnimation("idle")

    inst:AddTag("magicweapon")
    inst:AddTag("rangedweapon")

    inst:AddTag("weapon")
    inst:AddTag("show_spoilage")  -- 显示新鲜,猜的
    inst:AddTag("icebox_valid")   -- 可以被放入冰箱

    inst:AddTag("rechargeable")   -- 可充能的(和可以发射多个飞镖有关)

    inst.projectiledelay = FRAMES -- 射弹延迟 1 帧

    MakeInventoryFloatable(inst)

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst._projectiles             = {}                                               -- 射弹表
    inst.max_projectiles          = TUNING.VOIDCLOTH_BOOMERANG_PROJECTILE.MAX_ACTIVE -- 最大射弹数量 3 个

    -- 附着在实体表里的的函数
    inst.OnProjectileCountChanged = OnProjectileCountChanged

    -----------------------------------------------------------

    inst:AddComponent("equippable")
    inst.components.equippable.walkspeedmult = TUNING.VOIDCLOTH_BOOMERANG_SPEEDMULT
    inst.components.equippable:SetOnEquip(OnEquip)
    inst.components.equippable:SetOnUnequip(OnUnequip)

    inst:AddComponent("inspectable")
    inst:AddComponent("inventoryitem")

    inst:AddComponent("perishable")                                 -- 可腐烂组件
    inst.components.perishable:SetPerishTime(14400)                 -- 腐烂时间
    inst.components.perishable:StartPerishing()                     -- 开始腐烂
    inst.components.perishable.onperishreplacement = "spoiled_food" -- 腐烂后变成腐烂食物

    inst:AddComponent("forcecompostable")
    inst.components.forcecompostable.green = true

    inst:AddComponent("weapon")
    inst.components.weapon:SetRange(TUNING.VOIDCLOTH_BOOMERANG_ATTACK_DIST, TUNING.VOIDCLOTH_BOOMERANG_ATTACK_DIST_MAX)
    inst.components.weapon:SetProjectile("tf_floral_butterfly_fan_proj")

    inst:AddComponent("rechargeable")
    inst.components.rechargeable:SetOnDischargedFn(OnDischarged)
    inst.components.rechargeable:SetOnChargedFn(OnCharged)

    inst.OnPreLoad = OnPreLoad

    MakeHauntableLaunch(inst)

    return inst
end

----------------------------------------------------------------------------------------------------------------

local PROJECTILE_COLLECT_DIST_SQ = 1 * 1

local PROJECTILE_MAX_SIZE = 1
local PROJECTILE_MIN_SIZE = .4

local PROJECTILE_RETURN_SPEED_ACCELERATION_RATE = 1 / 3

-- 射弹移除
local function Projectile_OnRemoved(inst)
    if inst._boomerang ~= nil and inst._boomerang:IsValid() then
        table.removearrayvalue(inst._boomerang._projectiles, inst)

        inst._boomerang:OnProjectileCountChanged()
    end
end

-- 射弹返回
local function Projectile_ReturnToThrower(inst, thrower)
    inst.scalingdata = {
        start = inst.scale or PROJECTILE_MAX_SIZE,
        finish = PROJECTILE_MIN_SIZE,
        -- 回旋镖距离 12 / 返回速度 7.5
        totaltime = TUNING.BOOMERANG_DISTANCE / TUNING.VOIDCLOTH_BOOMERANG_PROJECTILE.RETURN_SPEED,
        currenttime = 0,
    }

    inst._returntarget = thrower -- 返回的对象

    -- 解除船,陆地海洋的碰撞限制
    inst.Physics:ClearCollidesWith(COLLISION.LIMITS)
    inst.Physics:SetMotorVel(TUNING.VOIDCLOTH_BOOMERANG_PROJECTILE.RETURN_SPEED, 0, 0) -- 直译为设置电机速度
end

local function Projectile_OnHit(inst, attacker, target)
    inst:ReturnToThrower(attacker)

    if target ~= nil and target:IsValid() then
        local fx = SpawnPrefab("voidcloth_boomerang_impact_fx")

        local radius = math.max(0, target:GetPhysicsRadius(0) - .5)
        local angle = (inst.Transform:GetRotation() + 180) * DEGREES
        local x, y, z = target.Transform:GetWorldPosition()

        x = x + math.cos(angle) * radius
        z = z - math.sin(angle) * radius

        fx.Transform:SetPosition(x, y, z)
    end
end

local function Projectile_OnMiss(inst, attacker, target)
    inst:ReturnToThrower(attacker)
end

local function Projectile_OnUpdateFn(inst, dt)
    local scalingdata = inst.scalingdata or {}

    if inst._returntarget == nil then
        -- 返回目标为空就啥也不干
    elseif not inst._returntarget:IsValid() or inst._returntarget:IsInLimbo() then
        inst:Remove()

        return
    else
        local p_pos = inst:GetPosition()               -- 射弹位置
        local t_pos = inst._returntarget:GetPosition() -- 返回目标位置

        if distsq(p_pos, t_pos) < PROJECTILE_COLLECT_DIST_SQ then
            -- 两者相差距离小于 1 就移除射弹
            inst:Remove()

            return
        else
            local direction = (t_pos - p_pos):GetNormalized() -- 方向
            local projected_speed = TUNING.VOIDCLOTH_BOOMERANG_PROJECTILE.RETURN_SPEED * TheSim:GetTickTime() * TheSim:GetTimeScale()
            local projected = p_pos + direction * projected_speed

            if direction:Dot(t_pos - projected) < 0 then
                inst:Remove()

                return
            end

            inst:FacePoint(t_pos)

            local speed_mult = math.max(1, scalingdata.currenttime * PROJECTILE_RETURN_SPEED_ACCELERATION_RATE)
            inst.Physics:SetMotorVel(TUNING.VOIDCLOTH_BOOMERANG_PROJECTILE.RETURN_SPEED * speed_mult, 0, 0)
        end
    end

    if scalingdata.totaltime == nil then
        return
    end

    scalingdata.currenttime = (scalingdata.currenttime or 0) + dt

    if scalingdata.currenttime >= scalingdata.totaltime then
        inst.scale = scalingdata.finish
    else
        inst.scale = Lerp(scalingdata.start, scalingdata.finish, scalingdata.currenttime / scalingdata.totaltime)
    end

    if inst.scale ~= nil then
        inst.AnimState:SetScale(inst.scale, inst.scale)
        inst.components.weapon:SetDamage(40)
    end
end

local function Projectile_OnThrown(inst, owner, target, attacker)
    inst.SoundEmitter:PlaySound("rifts4/voidcloth_boomerang/throw_lp", "loop")

    inst._boomerang = owner
    inst._bonusenabled = owner ~= nil and owner._bonusenabled

    if inst._bonusenabled then
        inst.components.planardamage:AddBonus(inst, TUNING.WEAPONS_VOIDCLOTH_SETBONUS_PLANAR_DAMAGE, "setbonus")
    end

    if owner ~= nil and owner.components.weapon ~= nil then
        owner.components.weapon:OnAttack(attacker, target, inst)

        table.insert(owner._projectiles, inst)

        owner:OnProjectileCountChanged()
    end

    if attacker ~= nil and attacker:IsValid() then
        local fx = SpawnPrefab("voidcloth_boomerang_launch_fx")

        local pos = target:GetPositionAdjacentTo(attacker, .5)

        fx.Transform:SetPosition(pos:Get())
        fx.Transform:SetRotation(fx:GetAngleToPoint(target.Transform:GetWorldPosition()) - 90)
    end
end

-- 脱离加载范围
local function OnEntitySleep(inst)
    inst.components.projectile:Stop()
    inst:Remove()
end

----------------------------------------------------------------------------------------------------------------

local function ProjectileFn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddSoundEmitter()
    inst.entity:AddNetwork()

    MakeProjectilePhysics(inst)

    inst.AnimState:SetBank("tf_floral_butterfly_fan_proj")
    inst.AnimState:SetBuild("tf_floral_butterfly_fan_proj")
    inst.AnimState:PlayAnimation("projectile", true)

    inst.AnimState:SetScale(PROJECTILE_MIN_SIZE, PROJECTILE_MIN_SIZE) -- 初始大小原动画大小的 0.4 倍

    inst.AnimState:SetLightOverride(.1)
    inst.AnimState:SetSymbolLightOverride("lightning", .5)

    -- 设置 blade 符号的颜色
    inst.AnimState:SetSymbolMultColour("blade", 1, 1, 1, .8)
    inst.AnimState:SetBloomEffectHandle("shaders/anim.ksh") -- 设置绽放效果

    inst:AddTag("weapon")

    inst:AddTag("projectile")

    inst:AddTag("NOCLICK") -- 不可以被点击
    inst:AddTag("NOBLOCK") -- 不可以被锁定

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    -- 缩放数据
    inst.scalingdata = {
        start = PROJECTILE_MIN_SIZE,  -- 最小 0.4 倍
        finish = PROJECTILE_MAX_SIZE, -- 最大 1 倍
        -- 总时间: 攻击距离 10 / 射弹发射速度 15
        totaltime = TUNING.VOIDCLOTH_BOOMERANG_ATTACK_DIST / TUNING.VOIDCLOTH_BOOMERANG_PROJECTILE.LAUNCH_SPEED,
        currenttime = 0, -- 直译为当前时间
    }

    inst.persists = false -- 参数直译意思是持续,本页面没有使用,以防万一留着吧

    inst.ReturnToThrower = Projectile_ReturnToThrower

    inst:AddComponent("weapon")
    inst.components.weapon:SetDamage(40) -- 40 点伤害

    inst:AddComponent("updatelooper")
    inst.components.updatelooper:AddOnUpdateFn(Projectile_OnUpdateFn)

    inst:AddComponent("projectile")
    inst.components.projectile:SetSpeed(TUNING.VOIDCLOTH_BOOMERANG_PROJECTILE.LAUNCH_SPEED)
    inst.components.projectile:SetRange(20)
    inst.components.projectile:SetOnHitFn(Projectile_OnHit)
    inst.components.projectile:SetOnMissFn(Projectile_OnMiss)
    inst.components.projectile:SetOnThrownFn(Projectile_OnThrown)
    inst.components.projectile.has_damage_set = true

    inst.OnRemoveEntity = Projectile_OnRemoved
    inst.OnEntitySleep = OnEntitySleep

    return inst
end

----------------------------------------------------------------------------------------------------------------

return
    Prefab("tf_floral_butterfly_fan", fn, assets, prefabs),
    Prefab("tf_floral_butterfly_fan_proj", ProjectileFn, assets)
